package com.fdb.efp.flow.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

import com.fdb.efp.flow.service.vo.BizFlowNodeVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.fdb.efp.flow.service.dao.BizFlowInfoDao;
import com.fdb.efp.flow.service.dao.BizFlowNodeDao;
import com.fdb.efp.flow.service.dao.BizFlowProcessDao;
import com.fdb.efp.flow.service.dao.BizFlowRouteDao;
import com.fdb.efp.flow.service.dao.BizFlowTaskDao;
import com.fdb.efp.flow.service.dao.BizFlowTaskParamDao;
import com.fdb.efp.flow.service.domain.BizFlowInfo;
import com.fdb.efp.flow.service.domain.BizFlowNode;
import com.fdb.efp.flow.service.domain.BizFlowProcess;
import com.fdb.efp.flow.service.domain.BizFlowRoute;
import com.fdb.efp.flow.service.domain.BizFlowTask;
import com.fdb.efp.flow.service.domain.BizFlowTaskParam;
import com.fdb.efp.flow.service.facade.CopyBizFlowInfoService;
import com.fdb.basic.framework.core.base.AbstractFrameworkService;
import com.fdb.basic.framework.core.base.FrameworkService;
import com.fdb.basic.framework.core.constant.SequenceConstance;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;

@Service("copyBizFlowInfoService")
public class CopyBizFlowInfoServiceImpl extends AbstractFrameworkService implements CopyBizFlowInfoService, FrameworkService {
    
    private static Logger logger = LoggerFactory.getLogger(CopyBizFlowInfoServiceImpl.class);

    @Autowired
    private BizFlowInfoDao bizFlowInfoDao;
    @Autowired
    private BizFlowNodeDao bizFlowNodeDao;
    @Autowired
    private BizFlowTaskDao bizFlowTaskDao;
    @Autowired
    private BizFlowTaskParamDao bizFlowTaskParamDao;
    @Autowired
    private BizFlowProcessDao bizFlowProcessDao;
    @Autowired
    private BizFlowRouteDao bizFlowRouteDao;
    
    @Override
    public boolean copyOfBizFlowId(String bizFlowId, String legalOrgCode, String createUser) throws Exception {
        List<String> oldBizNodeIds = null;//节点ID
        List<String> oldTaskIds = null;//任务ID
        
        Map<String, String> newAndOldNodeIds = null;//新旧节点ID映射
        Map<String, String> newAndOldTaskIds = null;//新旧任务ID映射
        
        //查询业务流转配置
        BizFlowInfo bizFlowInfo = new BizFlowInfo();
        bizFlowInfo.setBizFlowId(bizFlowId);
        bizFlowInfo = bizFlowInfoDao.queryByPk(bizFlowInfo);
        if(Objects.isNull(bizFlowInfo)) {
            logger.error("根据业务流转ID["+bizFlowId+"]查询业务流转配置为空！");
            throw new Exception("根据业务流转ID["+bizFlowId+"]查询业务流转配置为空！");
        }
        
        //查询业务流转节点配置
        BizFlowNodeVO bizFlowNode = new BizFlowNodeVO();
        bizFlowNode.setBizFlowId(bizFlowId);
        List<BizFlowNode> listBizFlowNode = bizFlowNodeDao.queryAllByFlowId(bizFlowNode);
        if(Objects.isNull(listBizFlowNode)||listBizFlowNode.size()==0) {
            logger.error("根据业务流转ID["+bizFlowId+"]查询业务流转节点配置为空！");
            throw new Exception("根据业务流转ID["+bizFlowId+"]查询业务流转节点配置为空！");
        } else {
            if(Objects.isNull(oldBizNodeIds)) {
                oldBizNodeIds = new ArrayList<>();
            }
            for(BizFlowNode node : listBizFlowNode) {
                oldBizNodeIds.add(node.getBizNodeId());
            }
        }
        
        //查询业务流转节点任务配置
        List<BizFlowTask> listBizFlowTask = bizFlowTaskDao.queryTaskByBizNodeIds(oldBizNodeIds);
        if(Objects.isNull(listBizFlowTask)||listBizFlowTask.size()==0) {
            logger.error("根据业务流转ID["+bizFlowId+"]查询业务流转节点任务配置为空！");
            throw new Exception("根据业务流转ID["+bizFlowId+"]查询业务流转节点任务配置为空！");
        } else {
            if(Objects.isNull(oldTaskIds)) {
                oldTaskIds = new ArrayList<>();
            }
            for(BizFlowTask task : listBizFlowTask) {
                oldTaskIds.add(task.getTaskId());
            }
        }
        
        //查询业务流转节点任务参数配置
        List<BizFlowTaskParam> listBizFlowTaskParam = bizFlowTaskParamDao.queryTaskParamsByTaskIds(oldTaskIds);
        if(Objects.isNull(listBizFlowTaskParam)||listBizFlowTaskParam.size()==0) {
            logger.error("根据业务流转ID["+bizFlowId+"]查询业务流转节点任务参数配置为空！");
            throw new Exception("根据业务流转ID["+bizFlowId+"]查询业务流转节点任务参数配置为空！");
        }
        
        //查询业务流转过程配置
        List<BizFlowProcess> listBizFlowProcess = bizFlowProcessDao.queryBizFlowProcessByBizFlowId(bizFlowId);
        
        //查询业务流转路由信息
        List<BizFlowRoute> listBizFlowRoute = bizFlowRouteDao.queryBizFlowRouteByBizFlowId(bizFlowId);
        
        //新业务流转配置
        String newBizFlowId = this.getSequence(SequenceConstance.BIZ_FLOW_SEQ_ID);//业务流转ID
        BizFlowInfo newBizFlowInfo = bizFlowInfo;
        newBizFlowInfo.setBizFlowId(newBizFlowId);//业务流转ID
        newBizFlowInfo.setBizFlowName("copyOf"+bizFlowInfo.getBizFlowName());
        newBizFlowInfo.setLegalOrgCode(legalOrgCode);//法人机构代码
        newBizFlowInfo.setCreateUser(createUser);//创建用户
        newBizFlowInfo.setCreateTime(TimeUtil.getCurrentDateTime());//创建时间
        newBizFlowInfo.setLastUpdateUser(createUser);//最后更新用户
        newBizFlowInfo.setLastUpdateTime(TimeUtil.getCurrentDateTime());//最后更新时间
        
        //新业务流转节点配置
        List<BizFlowNode> newBizFlowNodeList = new ArrayList<>();
        for(BizFlowNode node : listBizFlowNode) {
            if(Objects.isNull(newAndOldNodeIds)) {
                newAndOldNodeIds = new HashMap<>();
            }
            String newNodeId = this.getSequence(SequenceConstance.BIZ_FLOW_NODE_SEQ_ID);//节点ID
            newAndOldNodeIds.put(node.getBizNodeId(), newNodeId);
        }
        for(BizFlowNode node : listBizFlowNode) {
            node.setBizFlowId(newBizFlowId);//业务流转ID
            node.setBizNodeId(newAndOldNodeIds.get(node.getBizNodeId()));//节点ID
            newBizFlowNodeList.add(node);
        }
        
        //新业务流转节点任务配置
        List<BizFlowTask> newBizFlowTaskList = new ArrayList<>();
        for(BizFlowTask task : listBizFlowTask) {
            if(Objects.isNull(newAndOldTaskIds)) {
                newAndOldTaskIds = new HashMap<>();
            }
            String newTaskId = this.getSequence(SequenceConstance.BIZ_FLOW_TASK_SEQ_ID);//任务ID
            newAndOldTaskIds.put(task.getTaskId(), newTaskId);
        }
        for(BizFlowTask task : listBizFlowTask) {
            task.setTaskId(newAndOldTaskIds.get(task.getTaskId()));//任务ID
            task.setBizNodeId(newAndOldNodeIds.get(task.getBizNodeId()));//节点ID
            String previousTaskId = task.getPreviousTaskId();//前一个节点
            if(StringUtil.isNotEmpty(previousTaskId)) {
                task.setPreviousTaskId(newAndOldTaskIds.get(previousTaskId));//前一个节点ID
            }
            newBizFlowTaskList.add(task);
        }
        
        //新业务流转节点任务参数配置
        List<BizFlowTaskParam> newBizFlowTaskParamList = new ArrayList<>();
        for(BizFlowTaskParam taskParam : listBizFlowTaskParam) {
            taskParam.setTaskId(newAndOldTaskIds.get(taskParam.getTaskId()));//任务ID
            newBizFlowTaskParamList.add(taskParam);
        }
        
        //新业务流转过程配置
        List<BizFlowProcess> newBizFlowProcessList = null;
        if(Objects.nonNull(listBizFlowProcess)&&listBizFlowProcess.size()>0) {
            newBizFlowProcessList = new ArrayList<>();
            for(BizFlowProcess process : listBizFlowProcess) {
                process.setBizFlowId(newBizFlowId);//业务流程ID
                process.setBizNodeId(newAndOldNodeIds.get(process.getBizNodeId()));
                newBizFlowProcessList.add(process);
            }
        }
        
        //新业务流转路由信息
        List<BizFlowRoute> newBizFlowRouteList = null;
        if(Objects.nonNull(listBizFlowRoute)&&listBizFlowRoute.size()>0) {
            newBizFlowRouteList = new ArrayList<>();
            for(BizFlowRoute route : listBizFlowRoute) {
                route.setBizRouteId(UUID.randomUUID().toString().toString().toUpperCase().replaceAll("-", ""));
                route.setBizFlowId(newBizFlowId);//业务流程ID
                route.setBizSourceNodeId(newAndOldNodeIds.get(route.getBizSourceNodeId()));//源业务节点标识
                route.setBizTargetNodeId(newAndOldNodeIds.get(route.getBizTargetNodeId()));//目标业务节点标识
                newBizFlowRouteList.add(route);
            }
        }
        
        //插入数据
        bizFlowInfoDao.insertBizFlowInfo(newBizFlowInfo);
        bizFlowNodeDao.batchInsertBizFlowNode(newBizFlowNodeList);
        bizFlowTaskDao.batchInsertBizFlowTask(newBizFlowTaskList);
        bizFlowTaskParamDao.batchInsertBizFlowTaskParam(newBizFlowTaskParamList);
        bizFlowProcessDao.batchInsertBizFlowProcess(newBizFlowProcessList);
        bizFlowRouteDao.batchInsertBizFlowRoute(newBizFlowRouteList);
        
        return true;
    }

    @Override
    public boolean compareTwoFlowAndUpdateTarget(String srcBizFlowId, String targetBizFlowId) throws Exception {
        /*
         * 注意：此方法只实现了事件层面的差异更新到目标流程，更细致的差异并未实现！！！！！！！！
         */
        logger.info("比较两个流程差异，并更新目标流程，源流程ID["+srcBizFlowId+"]，目标流程ID["+targetBizFlowId+"]");
        if(StringUtil.isStrEmpty(srcBizFlowId) || StringUtil.isStrEmpty(targetBizFlowId)) {
            throw new Exception("源流程ID和目标流程ID均不能为空！");
        }
        
        //比较源流程和目标流程的流程类型，不一样不允许继续处理
        BizFlowInfo srcBizFlowInfo = new BizFlowInfo();
        srcBizFlowInfo.setBizFlowId(srcBizFlowId);
        srcBizFlowInfo = bizFlowInfoDao.queryByPk(srcBizFlowInfo);
        logger.info("源流程信息：" + JSONObject.toJSONString(srcBizFlowInfo));
        
        BizFlowInfo targetBizFlowInfo = new BizFlowInfo();
        targetBizFlowInfo.setBizFlowId(targetBizFlowId);
        targetBizFlowInfo = bizFlowInfoDao.queryByPk(targetBizFlowInfo);
        logger.info("目标流程信息：" + JSONObject.toJSONString(targetBizFlowInfo));
        
        if(!srcBizFlowInfo.getBizFlowType().equals(targetBizFlowInfo.getBizFlowType())) {
            throw new Exception("源流程和目标流程的流程类型不一致！");
        }
        
        List<BizFlowProcess> diffProcessList = bizFlowProcessDao.queryDiffProcessFromTwoBizFlow(srcBizFlowId, targetBizFlowId);
        if(Objects.nonNull(diffProcessList) && diffProcessList.size()>0) {
            //新流转配置列表
            List<BizFlowProcess> targetAddProcessList = new ArrayList<>();
            //新节点列表
            List<BizFlowNode> targetAddNodeList = new ArrayList<>();
            //新节点任务列表
            List<BizFlowTask> targetAddTaskList = new ArrayList<>();
            //新节点任务参数列表
            List<BizFlowTaskParam> targetAddTaskParamList = new ArrayList<>();
            //新路由列表
            List<BizFlowRoute> targetAddRouteList = new ArrayList<>();
            
            List<String> oldBizNodeIds = new ArrayList<>();//节点ID
            List<String> oldTaskIds = new ArrayList<>();//任务ID
            
            Map<String, String> newAndOldNodeIds = new HashMap<>();//新旧节点ID映射
            Map<String, String> newAndOldTaskIds = new HashMap<>();//新旧任务ID映射
            
            for(BizFlowProcess diffProcess : diffProcessList) {
                oldBizNodeIds.add(diffProcess.getBizNodeId());//源流程节点ID
                String newNodeId = this.getSequence(SequenceConstance.BIZ_FLOW_NODE_SEQ_ID);//节点ID
                newAndOldNodeIds.put(diffProcess.getBizNodeId(), newNodeId);
                
                diffProcess.setBizFlowId(targetBizFlowId);//目标流程ID
                diffProcess.setBizNodeId(newNodeId);//目标节点
                targetAddProcessList.add(diffProcess);
            }
            
            //查询源节点信息
            List<BizFlowNode> oldBizFlowNodes = bizFlowNodeDao.queryBizFlowNodeListByNodeIds(oldBizNodeIds);
            if(Objects.nonNull(oldBizFlowNodes)&&oldBizFlowNodes.size()>0) {
                for(BizFlowNode node : oldBizFlowNodes) {
                    node.setBizFlowId(targetBizFlowId);//目标流程ID
                    node.setBizNodeId(newAndOldNodeIds.get(node.getBizNodeId()));//目标节点
                    targetAddNodeList.add(node);
                }
            }
            
            //查询业务流转节点任务配置
            List<BizFlowTask> listBizFlowTask = bizFlowTaskDao.queryTaskByBizNodeIds(oldBizNodeIds);
            if(Objects.nonNull(listBizFlowTask)&&listBizFlowTask.size()>0) {
                for(BizFlowTask task : listBizFlowTask) {
                    oldTaskIds.add(task.getTaskId());
                    String newTaskId = this.getSequence(SequenceConstance.BIZ_FLOW_TASK_SEQ_ID);//任务ID
                    newAndOldTaskIds.put(task.getTaskId(), newTaskId);
                    
                    task.setBizNodeId(newAndOldNodeIds.get(task.getBizNodeId()));//目标节点
                    task.setTaskId(newTaskId);//任务ID
                    targetAddTaskList.add(task);
                }
            }
            
            //查询业务流转节点任务参数配置
            List<BizFlowTaskParam> listBizFlowTaskParam = bizFlowTaskParamDao.queryTaskParamsByTaskIds(oldTaskIds);
            if(Objects.nonNull(listBizFlowTaskParam)&&listBizFlowTaskParam.size()>0) {
                for(BizFlowTaskParam taskParam : listBizFlowTaskParam) {
                    taskParam.setTaskId(newAndOldTaskIds.get(taskParam.getTaskId()));//任务ID
                    targetAddTaskParamList.add(taskParam);
                }
            }
            
            //查询路由配置的差异
            List<BizFlowRoute> listBizFlowRoute = bizFlowRouteDao.queryDiffRouteFromTwoBizFlow(srcBizFlowId, targetBizFlowId);
            if(Objects.nonNull(listBizFlowRoute)&&listBizFlowRoute.size()>0) {
                for(BizFlowRoute route : listBizFlowRoute) {
                    route.setBizRouteId(UUID.randomUUID().toString().toString().toUpperCase().replaceAll("-", ""));
                    route.setBizFlowId(targetBizFlowId);//目标流程ID
                    route.setBizSourceNodeId(newAndOldNodeIds.get(route.getBizSourceNodeId()));//源业务节点标识
                    route.setBizTargetNodeId(newAndOldNodeIds.get(route.getBizTargetNodeId()));//目标业务节点标识
                    targetAddRouteList.add(route);
                }
            }
            
            if(Objects.nonNull(targetAddNodeList)&&targetAddNodeList.size()>0) {
                bizFlowNodeDao.batchInsertBizFlowNode(targetAddNodeList);
            }
            if(Objects.nonNull(targetAddTaskList)&&targetAddTaskList.size()>0) {
                bizFlowTaskDao.batchInsertBizFlowTask(targetAddTaskList);
            }
            if(Objects.nonNull(targetAddTaskParamList)&&targetAddTaskParamList.size()>0) {
                bizFlowTaskParamDao.batchInsertBizFlowTaskParam(targetAddTaskParamList);
            }
            if(Objects.nonNull(targetAddProcessList)&&targetAddProcessList.size()>0) {
                bizFlowProcessDao.batchInsertBizFlowProcess(targetAddProcessList);
            }
            if(Objects.nonNull(targetAddRouteList)&&targetAddRouteList.size()>0) {
                bizFlowRouteDao.batchInsertBizFlowRoute(targetAddRouteList);
            }
        }
        return true;
    }

}
